<template>
  <div id="go2-table">
    <!-- 表格工具栏 -->
    <div class="go2-table-tool" v-if="allToolbar">
      <!-- 自定义工具栏 -->
      <div class="go2-table-prev">
        <template :key="index" v-for="(item, index) in toolbar">
          <!-- 更多按钮 -->
          <template
            :value="item.code ? item.code : false"
            v-if="item.children && item.children.length > 0"
          >
            <a-dropdown>
              <a-button @click="item.event(selectedRowKeys)">
                {{ t(item.label) }}
              </a-button>
              <template #overlay>
                <a-menu>
                  <!-- 遍历子集 -->
                  <go2-authority
                    v-for="(child, i) in item.children"
                    :key="i"
                    :value="child.code ? item.code : false"
                  >
                    <a-menu-item>
                      <a @click="child.event(selectedRowKeys)">
                        {{ t(child.label) }}
                      </a>
                    </a-menu-item>
                  </go2-authority>
                </a-menu>
              </template>
            </a-dropdown>
          </template>
          <go2-authority :value="item.code ? item.code : false" v-else>
            <a-button 
               :disabled="item.disabled??false" 
              :type="index == 0 ? 'primary' : 'default'"
              @click="item.event(selectedRowKeys)"
            >
              {{ t(item.label) }}
            </a-button>
          </go2-authority>
        </template>
      </div>
      <!-- 默认工具栏 -->
      <div class="go2-table-next" v-if="defaultToolbar">
        <!-- 刷新工具栏 -->
        <a-button @click="reload">
          <template #icon><SyncOutlined /></template>
        </a-button>
        <!-- 过滤工具栏 -->
        <a-dropdown>
          <a-button>
            <template #icon><AppstoreOutlined /></template>
          </a-button>
          <template #overlay>
            <a-menu class="filtration">
              <a-checkbox-group
                v-model:value="filtrationColumnKeys"
                @change="filtration"
              >
                <a-row>
                  <!-- 遍历字段 -->
                  <a-col
                    :span="24"
                    :key="index"
                    v-for="(filtrationColumn, index) in filtrationColumns"
                  >
                    <a-checkbox :value="filtrationColumn.value">
                      {{ t(filtrationColumn.label) }}
                    </a-checkbox>
                  </a-col>
                </a-row>
              </a-checkbox-group>
            </a-menu>
          </template>
        </a-dropdown>
        <!-- 过滤工具栏 -->
        <a-dropdown>
          <a-button>
            <template #icon><ColumnHeightOutlined /></template>
          </a-button>
          <template #overlay>
            <a-menu :selectedKeys="[size]">
              <a-menu-item @click="changeSize('default')" key="default">{{
                t("default size")
              }}</a-menu-item>
              <a-menu-item @click="changeSize('middle')" key="middle">{{
                t("middle size")
              }}</a-menu-item>
              <a-menu-item @click="changeSize('small')" key="small">{{
                t("small size")
              }}</a-menu-item>
            </a-menu>
          </template>
        </a-dropdown>
        <a-button @click="print">
          <template #icon><PrinterOutlined /></template>
        </a-button>
      </div>
    </div>

    <!-- 自定义搜索 -->
    <a-form v-if="lineSearch" :model="formState">
      <table
        style="table-layout: fixed; width: 100%; margin: 10px 0"
        class="bg-lightgray"
      >
        <td style="width: 32px">
          <a-button
            style="
              height: 32px !important;
              width: 30px !important;
              padding: 0 !important;
            "
            type="primary"
            class="go2-query-button"
            @click="search"
          >
            <go2-icon type="SearchOutlined"></go2-icon>
          </a-button>
        </td>
        <template v-for="column in columns">
          <td
            :style="{
              width: isNaN(column.width) ? column.width : column.width + 'px',
            }"
          >
            <template v-if="column.dataIndex != 'operate'">
              <a-select
                v-if="column.conver"
                v-model:value="formState[column.dataIndex]"
                style="width: 100%"
                :readonly="column.defaultSearch ? true : false"
              >
                <a-select-option
                  :value="typeof column.conver[0].value == 'string' ? '' : 0"
                >
                  {{ t("all") }}
                </a-select-option>
                <a-select-option
                  v-for="(data, index) in column.conver"
                  :key="index"
                  :value="data.value"
                >
                  {{ t(data.label) }}
                </a-select-option>
              </a-select>

              <a-select
                v-else-if="column.switch"
                v-model:value="formState[column.dataIndex]"
                style="width: 100%"
                :readonly="column.defaultSearch ? true : false"
              >
                <a-select-option
                  :value="typeof column.switch.yes == 'string' ? '' : 0"
                >
                  {{ t("all") }}
                </a-select-option>

                <a-select-option :value="column.switch.yes">
                  {{ t("open") }}
                </a-select-option>
                <a-select-option :value="column.switch.no">
                  {{ t("close") }}
                </a-select-option>
              </a-select>

              <template v-else>
                <a-input-number
                  v-if="column.format && 'number' == column.format.type"
                  style="width: 100%"
                  :placeholder="
                    column.title ? t(column.title) : t(column.dataIndex)
                  "
                  v-model:value="
                    formState[
                      Array.isArray(column.dataIndex)
                        ? column.dataIndex.join('.')
                        : column.dataIndex
                    ]
                  "
                  type="text"
                  :readonly="column.defaultSearch ? true : false"
                />
                <a-range-picker
                  v-else-if="column.format && column.format.type == 'date'"
                  v-model:value="
                    formState[
                      Array.isArray(column.dataIndex)
                        ? column.dataIndex.join('.')
                        : column.dataIndex
                    ]
                  "
                  style="width: 100%"
                  :ranges="ranges"
                  :format="column.format.value"
                  :readonly="column.defaultSearch ? true : false"
                />

                <a-input
                  v-else
                  :placeholder="
                    column.title ? t(column.title) : t(column.dataIndex)
                  "
                  v-model:value="
                    formState[
                      Array.isArray(column.dataIndex)
                        ? column.dataIndex.join('.')
                        : column.dataIndex
                    ]
                  "
                  type="text"
                  :readonly="column.defaultSearch ? true : false"
                />
              </template>
            </template>
          </td>
        </template>
      </table>
    </a-form>

    <!-- 表格组件 -->
    <a-table
      :rowKey="rowKey"
      @change="fetchData"
      :columns="columns"
      :loading="loading"
      :pagination="pagination"
      :dataSource="datasource"
      :row-selection="rowSelection"
      :size="size"
      :tableLayout="tableLayout"
      :customRow="customRow"
    >
      <template #headerCell="{ column }">
        <span>
          {{ column.title ? t(column.title) : t(column.dataIndex) }}
        </span>
      </template>

      <!-- 列转换 -->
      <template :key="index" #bodyCell="{ text, column, record }">
        <!-- 行操作 -->
        <span v-if="column.dataIndex == 'operate'">
          <template :key="i" v-for="(item, i) in operate">
            <!-- 下拉操作 -->
            <a-dropdown v-if="item.children && item.children.length > 0">
              <a> {{ t(item.label) }} </a>
              <template #overlay>
                <a-menu>
                  <!-- 遍历子集 -->
                  <go2-authority
                    v-for="(child, i) in item.children"
                    :key="i"
                    :value="child.code ? item.code : false"
                  >
                    <a-menu-item>
                      <a @click="child.event(selectedRowKeys)">
                        {{ t(child.label) }}
                      </a>
                    </a-menu-item>
                  </go2-authority>
                </a-menu>
              </template>
            </a-dropdown>
            <!-- 单个操作 -->
            <go2-authority :value="item.code ? item.code : false" v-else>
              <a @click="item.event(record)"> {{ t(item.label) }} </a>
              <a-divider type="vertical" v-if="i != operate.length - 1" />
            </go2-authority>
          </template>
        </span>

        <!-- 开关转换 -->
        <span v-else-if="column.switch">
          <a-switch
            @change="column.switch.event($event, record)"
            :checked="text === column.switch.yes"
          />
        </span>

        <!-- 文本转换 -->
        <span v-else-if="column.conver">
          <template v-for="(data, index) in column.conver">
            <span :key="index" v-if="data.value === text">
              <template v-if="data.tag">
                <a-tag :color="data.tag.color || 'green'">
                  {{ t(data.label) }}
                </a-tag>
              </template>
              <template v-else>
                {{ t(data.label) }}
              </template>
            </span>
          </template>
        </span>

        <!-- tag -->
        <span v-else-if="column.tag">
          <a-tag :color="column.tag.color || 'green'">
            {{ text }}
          </a-tag>
        </span>

        <!-- 格式化 -->
        <span v-else-if="column.format">
          <template v-if="column.format.type == 'date'"
            >{{ Moment(text).format(column.format.value) }}
          </template>
          <template v-else>{{ text }}</template>
        </span>

        <!-- 头像 -->
        <span v-else-if="column.avatar">
          <!-- 空头像 -->
          <a-avatar
            v-if="text == null"
            :size="column.avatar.size"
            :shape="column.avatar.shape"
          >
            <template #icon><UserOutlined /></template>
          </a-avatar>

          <!-- 非头像 -->
          <a-avatar
            v-else
            :src="text"
            :size="column.avatar.size"
            :shape="column.avatar.shape"
          />
        </span>

        <!-- 预览 -->
        <span v-else-if="column.image">
          <a-image :width="column.image.width" :src="text" />
        </span>

        <!-- 原样输出 -->
        <span v-else-if="record">
          {{ text }}
        </span>
      </template>
    </a-table>
  </div>
</template>

<script>
import { useI18n } from "vue-i18n";
import "./index.less";
import {
  defineComponent,
  onMounted,
  onUpdated,
  reactive,
  toRefs,
  watch,
  ref,
  toRaw,
  onUnmounted,
} from "vue";
import dayjs from "dayjs";
import {
  AppstoreOutlined,
  PrinterOutlined,
  SyncOutlined,
  UserOutlined,
  ColumnHeightOutlined,
} from "@ant-design/icons-vue";
import Moment from "moment";
export default defineComponent({
  name: "go2-table",
  components: {
    ColumnHeightOutlined,
    AppstoreOutlined,
    PrinterOutlined,
    SyncOutlined,
    UserOutlined,
  },
  /// 数据来源
  props: {
    /// 开启行搜索
    lineSearch: {
      type: Boolean,
      default: true,
    },
    rowKey: {
      type: String,
      default: "id",
    },
    /// 扩展参数
    param: {
      type: Object,
      default: {
        isInit: true,
      },
    },
    /// 数据来源
    fetch: {
      type: Function,
      required: false,
    },
    /// 数据解析
    columns: {
      type: Array,
      required: true,
    },
    //所有工具栏
    allToolbar: {
      type: Boolean,
      default: true,
    },
    /// 头工具栏
    toolbar: {
      type: Array,
    },
    defaultToolbar: {
      type: Boolean,
      default: true,
    },
    /// 行工具栏
    operate: {
      type: Array || Boolean,
      default: false,
    },
    /// 分页参数
    pagination: {
      type: [Object, Boolean],
      default: {
        page: 1,
        pageSize: 20,
      },
    },
    rowSelection: {
      type: Object,
    },
    customRow: {
      type: Object,
    },
    size: {
      type: String,
      default: "small",
    },
    tableLayout: {
      type: String,
      default: "fixed",
    },
    realyPagination: {
      type: Boolean,
      default: true,
    },
  },
  setup(props) {
    const { t } = useI18n();

    const formState = reactive({});
    /// 状态共享
    const state = reactive({
      pagination: props.pagination, // 分页
      datasource: [], // 数据源
      loading: true, // 加载
      columns: props.columns, // 字段
      filtrationColumnKeys: [], // 过滤
      filtrationColumns: [],
      filtration: () => {},
      selectedRowKeys: [], // 选中项
      size: props.size, // 表格大小
    });

    /// 默认操作
    if (props.operate != false) {
      state.columns.push({
        dataIndex: "operate",
        key: "operate",
        //title: "操作",
        fixed: "right",
      });
    }

    /// 为所有 column 新增默认 customRender 属性
    // state.columns.forEach((column) => {
    //     // column.slots = { customRender: column.dataIndex };
    // });

    /// 过滤字段
    const setFiltra = () => {
      let _filtrationColumns = [];
      let _filtrationColumnKeys = [];
      
      props.columns.forEach(function (item) {
        let _title = typeof item.title != "undefined" ? item.title : item.dataIndex;
        _filtrationColumns.push({
          label: _title,
          value: _title,
        });
        _filtrationColumnKeys.push(_title);
      });
      state.filtrationColumns = _filtrationColumns;
      state.filtrationColumnKeys = _filtrationColumnKeys;

      /// 过滤字段
      state.filtration = function (value) {
        state.columns = props.columns.filter((item) =>{
          let _title = typeof item.title != "undefined" ? item.title : item.dataIndex;
          return  value.includes(_title);
        
        });
        state.filtrationColumnKeys = value;
      };
    };
    setFiltra();

    /// 选中回调
    const onSelectChange = (selectedRowKeys) => {
      state.selectedRowKeys = selectedRowKeys;
    };

    /// search
    const search = () => {
      for (let key in formState) {
        props.param[key] = formState[key];
      }
      fetchData();
    };

    /// 数据请求
    const fetchData = async (pagechange) => {
      //开启分页
      if (props.pagination != false) {
        //真分页
        if (props.realyPagination) {
          /// 开启加载
          state.loading = true;

          /// 请求数据
          let datapost = Object.assign(
            {},
            state.pagination,
            pagechange,
            props.param
          );
          delete datapost.isInit;
          //点击查询的
          if (pagechange == undefined) {
            datapost.page = 1;
          } else {
            //点击分页相关
            datapost.page = datapost.current || datapost.page;
          }

          const { data } = await props.fetch(datapost);

          /// 状态重置
          if (state.pagination != false) {
            state.pagination.total = data.total;
            state.pagination.current = data.page;
            state.pagination.pageSize = data.pageSize;
          }
          state.datasource = typeof data.list == "undefined" ? data : data.list;
          state.loading = false;
        } else {
          state.pagination.pageSize = pagination.pageSize;
          state.pagination.current = pagination.page;
        }
      } else {
        //关闭分页
        /// 开启加载
        state.loading = true;
        /// 请求数据
        let datapost = Object.assign({}, props.param);
        delete datapost.isInit;
        const { data } = await props.fetch(datapost);
        state.datasource =
          data != null && typeof data.list != "undefined" ? data.list : data;
        state.loading = false;
      }
    };

    /// 刷新方法
    const reload = function () {
      fetchData();
    };

    onUpdated(() => {
      //监听回车事件
      document.onkeydown = function (e) {
        if (e.keyCode == 13) {
          for (let key in formState) {
            props.param[key] = formState[key];
          }
          fetchData();
        }
      };
    });
    onUnmounted(() => { 
      document.onkeydown = null;
    });

    /// 初始数据
    onMounted(async () => {
      if (props.param.isInit !== false) {
        await fetchData();
      } else {
        state.loading = false;
      }

      /// 默认搜索
      let flag = false;
      props.columns.forEach(function (column) {
        if (column.defaultSearch) {
          flag = true;
          formState[
            Array.isArray(column.dataIndex)
              ? column.dataIndex.join(".")
              : column.dataIndex
          ] = column.defaultSearch;
        }
      });
      if (flag) {
        for (let key in formState) {
          props.param[key] = formState[key];
        }
        fetchData();
      }
    });

    /// 监听扩展参数, 触发表格刷新
    watch(
      () => props.param,
      () => {
        fetchData();
      }
      // { deep: true }
    );

    //监听列变化
    watch(
      () => props.columns,
      () => {
        state.columns = props.columns;
        setFiltra();
      }
    );

    /// 改变按钮尺寸
    const changeSize = (target) => {
      state.size = target;
    };

    /// 表格打印
    const print = function () {
      let subOutputRankPrint = document.getElementById("go2-table");
      let newContent = subOutputRankPrint.innerHTML;
      let oldContent = document.body.innerHTML;
      document.body.innerHTML = newContent;
      window.print();
      window.location.reload();
      document.body.innerHTML = oldContent;
    };

    const ranges = {
      Today: [dayjs(), dayjs()],
      "This Month": [dayjs(), dayjs().endOf("month")],
    };

    return {
      t,
      formState,
      search,
      /// 数据信息
      ...toRefs(state),
      /// 数据加载
      fetchData,
      /// 刷新方法
      reload,
      /// 选中字段
      onSelectChange,
      /// 改变大小
      changeSize,
      /// 打印
      print,
      Moment,
      ranges,
    };
  },
});
</script>